by Ibrahim Malluf
Visual Basic Script provides an almost complete set of sequential, looping, and branching structures. VBScript also only allows the 'On Error Resume Next' error handling structure, limiting Visual Basic Script to inline error control. That means Visual Basic programmers who are used to branching to labeled error-handling routines will have make do with this limited approach. Despite this major limitation on error handling, Visual Basic Script is a very robust programming platform for adding client-side scripting capabilities. Let us review the fundamental structures that comprise the basis of structured programming techniques and how they are implemented in Visual Basic Script.
Modern programming techniques revolve around structures. VBScript includes the three main types of structures: sequential, looping, and conditional branching. Different combinations and variations of these three structures are the tools that you'll use to accomplish the programming task at hand. What follows is description of each structure included in Visual Basic Script.
Sequential structures are the simplest of programming structures. They are the lines of code that actually perform the calculations, state changes, printing, input and output, and other required operations. They can also be branching instructions, such as a function or subroutine call. Generally speaking, sequential statements are almost always contained within other more complex structures. Listing 18.1 shows a set of five example sequential structures.
Listing 18.1 Simple Structure Statements
Looping structures cause program execution to repeat in a continuous loop until some condition is met. In Visual Basic Script, there are four different looping structures. They are called looping structures because the one common feature among them is that they repeat the same section of code until something causes the loop to end.
The Do...Loop structure continually repeats a block of code until a specified condition is met either before each loop or after each loop. What determines if the loop runs at least once depends on where the structure's conditional is placed and whether that conditional is a While or Until conditional. Let's take a look at the different ways you can construct a Do...Loop along with some example code that shows how the particular style can be used.
The following code shows all of the Do...Loop structure's possible syntactical variations. The conditionals that break the loop can be at the beginning, middle, or end of the loop. In the beginning or end of the loop structure you would use the While or Until keywords to indicate the conditional. In the middle of the loop you can use an If...Then structure to break out of the loop with an Exit Do statement as part of the If...Then's statements.
DO [WHILE|UNTIL condition]
[statements]
[EXIT DO]
LOOP [WHILE|UNTIL condition]
The following example runs only if the condition is met in the beginning and repeats as long as the condition is met.
DO WHILE condition
[statements]
LOOP
An example of this structure is shown in Listing 18.1. Here the statements inside of the Do...Loop will execute only if intPlace is less than or equal to 8 and repeat until intPlace is greater than 8. Also note that the Do...Loop will immediately exit if the intCount value exceeds the upper bounds of the strData array.
Listing 18.1 A Do While Example
The following runs only if condition is not met and repeats as long as the condition is not met.
DO UNTIL condition
[statements]
LOOP
[statements]
An example of this form of the Do...Loop structure is shown in Listing 18.2. Note that it is a minor modification of Listing 18.1 that does the exact same thing only using the Until keyword instead and will also repeat as long as intPlace is less than 8.
Listing 18.2 A Do Until Loop
The next example's Do...Loops always run at least once regardless of the loop's conditional requirements. This is because the conditional is not checked until the end of the loop's statements.
In this example a While statement is used for the conditional. In this case the loop will repeat as long as the condition is met.
DO
[statements]
LOOP WHILE condition
Continuing to use a slight modification of the same sample code, Listing 18.3 shows a Do...Loop that will always execute once, and if the condition is met will repeat again.
Listing 18.3 A Do Loop While Example
Finally the Do...Loop Until structure will repeat as long as the condition is not met.
DO
[statements]
LOOP UNTIL condition
Listing 18.4 shows the same example code this time using an Until condition structure.
Listing 18.4 A Do Loop Until Example
Figure 18.1 demonstrates the structure of the Do...Loop process.
FIG. 18.1
Logic Flow diagram of the Do...Loop structure.
Beware The Endless Loop! Make sure your looping structures have an explicit ending condition that must occur! When using a Do...Loop or While...Wend make sure that these loops have a definite ending condition; otherwise, you could end up locking up the browser from further interaction with the user. VBScript does not have the equivalent of a Visual Basic DoEvents() function, so there is no way to break out of a loop or allow other operations outside of the loop to occur.
These looping structures are used to repeat a given set of code based on a certain condition. The condition is usually the result of some calculation or other operation within the loop. It is possible, with multiple threads running in an application, for the condition to be affected from another operation independent of the Do...Loop itself, though relying on this can be dangerous. Looping structures must eventually arrive at a condition that allows the loop to end; otherwise, your application could lock up and stop responding to the user. This is especially true in Visual Basic Script because there is no mechanism like a DoEvents() function to allow breaking out of a loop through user intervention. Internet Explorer 3.0 will, after a particular operation has been looping for a while, ask if you want to end the script, but don't depend on other browsers to allow for this. Make sure your looping structures have a definite ending condition.
The For...Next loop has a counter that is initialized to some value and then increments or decrements that counter for every iteration of the loop until it has reached some specified value. See Figure 18.2 for a diagram of the logic flow of a For...Next loop.
The following code shows the syntax for For...Next loops:
FOR counter = start TO finish STEP rate
[statements]
[EXIT FOR]
NEXT
The counter is the numeric value being incremented or decremented, start is the starting value of the counter, finish is the final value that the counter either increments or decrements to, statements are the code statements to be executed within the loop, and rate is the amount that the counter's value changes with each interation. Figure 18.2 provides a logic flow diagram of a For...Next loop.
FIG. 18.2
The Logic Flow Diagram of a For...Next loop.
The STEP rate argument is optional and is required only if the rate of change is to be other than an increment of 1 per iteration. If you want the value of counter to increment 5 every interation, you use STEP 5 as part of the statement. If you want to decrement the count by 5, then use STEP -5.
In Visual Basic the placing of the counter name right after the Next statement has been a normal programming practice that actually saved CPU cycles that were noticable in long iterations of a loop. In VBScript this will produce an error because placing the counter after the Next statement is not supported.
While...Wend loops through a group of statements as long as a given condition is true. If the condition is True, then the statements between the While...Wend execute and return to the While statement to check if the condition is still True. If the condition is not True, execution resumes at the first line after the When statement. You can nest While...Wend statements. The syntax for While...Wend is shown in the following code:
WHILE condition
[statements]
WEND
condition is any operation that results in True or False. statements are the code statements to be executed within the loop. The example code in Listing 18.5 parses a string displaying each set of characters between ampersands. When it reaches the word "Stop" the loop ends.
Listing 18.5 Using the While...Wend Loop
Figure 18.3 shows the logic flow diagram of the While...Wend statement.
FIG. 18.3
The Logic Flow Diagram of the While...Wend loop.
That completes the looping structures for Visual Basic Script. The next structure type is a conditional-branching structure, known as the IF...THEN...ELSE structure.
Conditional branching structures cause the flow of program logic to change according to a specified set of criteria. In VBScript there are two conditional branching structures, the If...Then...Else structure and the Select Case structure.
What an If...Then...Else conditional-branching structure essentially does is this: if a condition is met, a group of statements executes. If the condition is not met and there is an ELSEIF condition that is met, then those statements immediately following the ELSEIF execute. There can be multiple ELSEIF conditionals within the structure allowing for a cascading set of If...Thens until a condition is met. Finally if none of the previously stated conditions are met, you can have an ELSE group of statements that executes. The following code shows the syntax for the If...Then...Else structure (see fig. 18.4):
IF condition THEN
[statements]
[ELSEIF condition THEN]
[statements]
[ELSE]
[statements]
END IF
condition is any operation that results in True or False. statements are the code statements to be executed within the branch.
The logic flow of the If....Then...Else conditional-branching structure.
You can have as many Else If...Then statements as needed in your script logic. You should always try to have an Else condition; at least consider the need for one carefully when constructing your logic. I automatically include it in any multiline If...Then structure and remove it only after I have positively identified that it is not needed. Listing 18.6 shows an exanple If...Then...Else that includes an If, ElseIf, and Else condition. The purpose of the example is to ensure that a value entered into a textbox is within a valid set of bounds before passing it to the rest of the program through the lngMLat variable. If the value entered is not valid then the previous value contained in lngMLat replaces the text in txtMLat. If the value entered is valid then the entered value replaces the value in lngMLat.
Listing 18.6 An Example If...Then...Else Structure
The Select Case structure takes a Value and compares that value to a list of conditions called Cases. The code within the first Case that matches the value gets executed. If there is a Case Else condition included in the structure then the code in that case will execute if none of the other cases matched the value. Here is the syntactical representation of the Select Case structure:
SELECT CASE testexpression
[CASE expressionlist-n
[statements-n]] . . .
[CASE ELSE expressionlist-n
[elsestatements-n]]
END SELECT
testexpression is any value or expression that represents the conditional
critria
CASE is any expression that matches the criteria contained in testexpression
expressionlist is an expression or value to be compared with the criteria
identified in testexpression statements is the code to execute for the
given expression.
The Select Case structure is well suited to situations where there is a large list of possible conditions to match up to. Listing 18.7 shows an example Select Case being used in conjunction with a Popup Menu control.
Listing 18.7 Using the Select case Structure
The code shown in Listing 18.7 compares the index of the menu item selected to a set of cases and executes the code where the case matches. Note that in this example I have a Case Else with no code to execute but a note saying that no else situation exists. On final review of this code, satisfied that there are no Else conditions to account for, I would remove the Case Else condition. Putting it there when I first write the skeleton structure reminds me to make sure that there are no possible conditions that I have overlooked and to allow for them if they do indeed exist.
This concludes the text on logic flow control for VBScript. All of the structures shown in this section are the building blocks that you use to construct your program logic. The next section covers the techniques of handling your program logic when errors occur.
Visual Basic Script allows only inline error handling in its present incarnation. What this means is that you must immediately check for an error condition after each statement that might possibly cause an error.
The error handler is invoked in the following manner:
On Error Resume Next
[Statement]
If Err then
[statements]
Else
[statements]
End If
Now some programmers prefer this style as opposed to using jumps to labels that handle errors. Myself, I prefer to be able to allow for only one place to enter a routine and one place to exit it using the following code structure:
Sub MySub ()
On Error Goto BadMySub
[statements]
ExitMySub:
[exit code statements]
Exit Sub
BadMySub:
[error handler statements]
If fixed THEN
Resume
Else
Resume ExitMySub
End If
End Sub
The advantage of the latter approach is the ability to provide an area for cleanup code that always executes regardless of any other circumstances within the procedure. With the inline method, if the error is fatal then you must exit immediately where you have determined this error to be fatal. If there is cleanup code that has to be included then you must repeat that code everywhere that this kind of error exit occurs. The opportunity for introducing even more errors due to procedural complexity is present. But inline error handling is what is provided in the current incarnation of VBScript.
The ERR object provides two methods and five properties, listed in Table 18.1.
Table 18.1 The ERR Object's Properties and Methods
Name | Type | Description |
Description | Property | String containing a description of the error. |
HelpContext | Property | Long integer pointing to a context in a help file. |
HelpFile | Property | String containing the path to the relevant help file. |
Number | Property | Long integer indicating the error number. |
Source | Property | The name of the object causing the error. |
Raise | Method | Causes a specified error to occur. |
Clear | Method | Clears the ERR object of error status. |
The Description property contains a short description of the error that was generated. You can use this string in a message box or an alert box to inform the user that an error has occurred. The HelpContext property provides a jump to a help topic within a specified help file when the user presses F1 or clicks the Help button on an message box. If no context is provided, it defaults to the contents window of the help file. The HelpFile property of ERR object is a fully qualified path to a help file. If no help file is specified, then the browser's default help file is invoked. The Number property corresponds to a Visual Basic error number or a user-defined error number and is specific to the type of error generated. This property is usually checked to determine the error that has occurred, and program logic is usually branched off accordingly. The Source property contains the name of the object where the error originated.
The Raise method has the following syntax:
object.RAISE (number[,source,description,helpcontext,helpfile])
object is always the ERR error object. number requires a long integer that specifies the error being raised. source is an optional string naming the object that originated the error. description is an optional string describing the error. helpcontext is an optional long integer pointing to a help topic in the specified help file. helpfile is an optional string specifying the full path to a relevant help file.
The Raise method is used to create an error condition in your code. In the context of Visual Basic Script, you can use this method to test and debug your own error handling code. It's original purpose was to generate a user-defined error condition in the Visual Basic environment from an OLE Automation object. Since Visual Basic Script does not allow you to create Automation objects, the use of the Raise method is probably limited to debugging your script code. The Clear method clears all of the property settings of the ERR object. An example of the Err.Object's use is given in Listing 18.8. This is a rewrite of the code shown in Listing 18.7. The While...Wend loop had a major flaw in it. Before going any farther, go back to that listing and see if you can determine what that flaw in that While...Wend loop was before reading on.
Listing 18.8 ERROBJ1.HTMùDoing Inline Error Handling with the Error Object
The flaw in Listing 18.7 was that there was the possibility of an endless loop if the strMyTest string did not contain a "Stop" in it. Or if the string was improperly formatted or empty an endless loop could also occur. So in Listing 18.8 I rewrote the code with an error handler that will catch either of these conditions and log them as an error and exit the subroutine. I created a user defined error using the number 99 and provided a description of the error for later display. I then check for an error condition, display it and exit the procedure.
The example in Listing 18.8 shows how to use the Raise method of the Err object for indicating an actual error condition in the code. You could also use the Raise method as an error assertion for testing your program's code ability to handle various error by introducing specific errors at strategic places with this method and observe the outcome of that contrived error.
Now we can get into some Visual Basic Script examples that will give you a taste of what is possible. If you have had any experience with HTML you know that up until recently almost all activity was on the server side of things. HTML has been getting more and more capability added with each revision. But still it lacks the essentials of a good programming language. Visual Basic Script gives your HTML documents the client-side capabilities that HTML doesn't have.
To get you started with a quick and impressive example, we will create a Web page with three rotating labels that display the current angles of the labels. We will also have the point size of the label text expand and contract.
The first order of things is to place all non-script elements on the page. Using a text editor like Notepad enter the code in Listing 18.8.
Listing 18.8 ROTATELABELS.HTMùHTML Portion of an HTML Document that Shows How to Place ActiveX Controls and Other Items on the Document
The code in Listing 16.3 places several label controls, a button control, and a text box on the form; the background color is set to teal. What we are going to do here is have three of the labels rotate their text in a circular pattern while changing the text to reflect the angle that they are currently at. Clicking the button control starts and stops the rotation. The text control's text changes to Running when the labels rotate and displays the current angle when the rotation stops.
The Visual basic Script portion of this example contains two procedures. The first procedure is an OnClick event of a button control. It utilizes a single If...Then...Else structure to toggle the timer control's enable property on and off. The second procedure is a timer event that contains a For...Next looping structure that iterates through the array of three label controls. Within the For...Next loop there are two If...Then structures. The first If...Then checks to see if the Icount property of the For...Next loop is an even or odd number and selects the direction of the rotation accordingly. The second If...Then loop compares the font size of the label against the maximum 20-point size points and increases or lowers the label's fontsize depending on the outcome of that comparison. Listing 18.9 shows the VBScript portion of the document that actually accomplishes these tasks.
Listing 18.9 ROTATELABELS.HTMùVBScript Portion of ROTATELABELS.HTM
Save the document as ROTATELABELS.HTM and load it into your Internet Exporer 3.0 browser. Click the Change Angle button. The three labels on the bottom should start rotating the text in opposite directions. So this isn't rocket science but I just wanted to get you started with a simple script that utilized a looping structure and a conditional-branching structure. See Figure 18.5 for an idea of what the Web page should look like.
The Rotating Labels from Listing 18.9.
Now let's move on to a more realistic and practical example of using Visual Basic Script. In the past, when a Web page was used for data entry, the user entered their data and clicked the Submit button. The data was then sent to the Web server; the server submitted the data to a server-side program, such as Perl, or a CGI script. If the data was missing items or improperly submitted, then the server-side script sent an error page back to the server that, in turn, sent the page back to the user informing him that his data was invalid. Given all the traffic on the Internet lately, this procedure could cause a considerable delayùjust to find out you forgot to enter something or that there was a typo.
Visual Basic Script gives you the ability to write pages that provide immediate client-side validation of data. When the user clicks that Submit button, your script can immediately validate the data for proscribed format and content. This is the theme of this chapter's next example. I make extensive use of If...Then structures in it. I also use a For...Next structure to iterate through the characters in a phone number field, formatting and validating it as I go.
The HTML code for formatting the document includes two ActiveX label controls, two command buttons, eight text entry controls, and a HTML table. Open a text editor and enter Listing 18.10's code for the body of the page.
Listing 18.10 CH7_3.HTMùHTML Code for the Client-Side Validation Page
If you haven't worked with HTML tables before, the code in Listing 16.5 gives you some idea just how easy they are to use. See Appendix B for more detailed information on tables.Figure 18.6 gives you an idea of what the resulting table looks like.
The Client-Side Data Validation page.
The Visual Basic Script is broken into two sections. The first section, Listing 18.11, contains the code underlying the two command buttons. It's short, easy to understand, and knows nothing about the validation functions that it calls. The sole purpose of the Submit button is to call the CheckAll() validation function; if it returns a True value, submit the data; and if it returns a False value, alert the user that there is a problem. The Clear button simply calls a routine that clears out all data on the page so that the user can start over with a clear page. What this means is that this first script is entirely independent of the underlying data structures and validation routines. If the data-entry requirements change at a later date, they only have to be changed in the actual validation functions contained in the second script. The more you can encapsulate functionality and limit the scope of data, the more secure your application is from inadvertently introducing errors by changing something in one place that is dependent on something in another.
By encapsulating your code as much as possible you protect yourself from cascading errors in design. Listing 18.11 shows the first script.
Listing 18.11 CH7_3.HTMùCommand Button Script for Client-Side Data Validation
I know, there's not a lot there. But this is the idea behind encapsulating your code. Notice that the procedure names clearly state their purpose in life. CheckAll() means to check all of the data, ClearAll means to clear all the data out, and NotifyUser notifies the user of the current status. The alerts that are used here are solely for demonstration and should be replaced with code that does something like submitting the data to the server.
The second script is much more involved, though still pretty simple. There are four procedures in the script. I present them in three sections. The first section contains the ClearAll and NotifyUser procedures. The third and fourth sections each contain one considerably more complex procedure.
The ClearAll procedure is very straightforward, using only sequential statements that sets text values and captions to empty strings. The NotifyUser procedure uses a simple If...Then...Else structure to display a message to the user based on the IsDataValid Boolean value. Listing 18.12 shows these two procedures:
Listing 18.12 CH7_3.HTMùThe ClearAll and NotifyUser Procedures of the Client-Side Data Validation Page
The CheckAll() function utilizes several If...Then structures to determine whether their respective text fields contain required data. In this example program, I only checked certain fields to make sure that they contain data. The exception to this is the Phone and Fax validation routines. They are If...Then...Else structures that call another function that actually checks each character for proper type and format. The CheckAll() function starts by assuming success and sets the IsDataValid variable to True. If any of the validation routines fails, they will set this value to False. They also set the ErrorNotes variable to contain their particular error message. Listing 18.13 shows the CheckAll() procedure's code.
Listing 18.13 CH7_3.HTMùThe CheckAll() Function of the Client-Side Data Validation Page
You'll notice that the Phone and Fax validation routines differ from the other validation routines in that there is an If...Then...Else nested within the If...Then structure. The outer conditional first checks to see if there is any data in the fields to begin with. Since in this application the Phone and Fax numbers are not required fields, The outer conditional skips validation if there is no data in the Phone or Fax fields. But if there is data, then the outer conditionals will call the IsUSPhone() function to ensure that the data entered is both valid and properly formatted.
The IsUSPhone() function validates only for North American phone standards, including the area code. Again in the case of the CheckAll() function, it is not concerned with how IsUSPhone() does its job, it only is concerned with getting a string with data back. If the string returned is empty, then it assumes an error condition and sets IsValidData to False. If it does get a non-empty string back it replaces the string in the Phone or Fax text control and continues on.
You may wonder what happens if the phone number is incomplete. The CheckAll() function is unconcerned with the format and flags correct but incomplete data as valid data. Well, I had to break the encapsulation rules here. Visual Basic Script does not support passing data arguments by reference; thus, I was not able to pass a modified argument back to the calling routine. The compromise was to use the function value itself to pass back a string if the data was valid in format and content. The problem is that I couldn't pass back the fact that the data was incomplete if it was incomplete.
The answer was to make IsDataValid global and change it's value in IsUSPhone() if the data was incomplete. Had I been able to pass the string back in a ByRef argument, I could have used the IsUSPhone() return value as a Boolean True or False value, thus indicating incomplete or invalid data by that value. Listing 18.14 shows the code for the IsUSPhone() procedure.
Listing 18.14 CH7_3.HTMùThe IsUSPhone() Procedure of the Client-Side Data Validation Page
The main feature of this function is the For...Next looping structure that iterates through each character in the MyText value that is passed to it. It checks each character for proper format position and value. If it finds one of the (, ), or - characters missing, it inserts them where they belong and continues on. If it finds characters that are not part of the phone number format or are not numeric where they should be or some other condition it cannot handle, the loop exits the function, returning an empty string. If it does complete its iteration through the string without incident, then the loop checks for proper length, chopping off any extra characters it finds. This validation routine is not the best algorithm I have ever written, but it does give you a strong indication of the possibilities using Visual Basic Script. Refer to Figure 18.6 for an illustration of the client-side validation example.
To add a little more functionality to this example I added a Timer control that checks the Phone and Fax entries to see if they are changed and if they are to run the IsUSPhone procedure to format them. Initially I would have thought that the changes in the text would be immediately evaluated, formatting the text as you typed. But it seems that the text is not available until after you leave the text box either by tabbing or clicking somewhere else on the page. Anyway, the code in Listing 18.15 adds the ability to validate the data as the user moves to another area, giving a more immediate response to data entry. Enter this code immediately after the <Body> tag on your HTML document.
Listing 18.11 CH7_4CSV.HTMùAdding the Timer Control
In the second Visual Basic Script module add the Timer event code shown in Listing 18.16.
Listing 18.16 CH7_4CSD.HTMùTimer Event Code for Immediate Data Validation
Once added, the Timer calls the validation routines for the Phone and Fax entries. The validation effects won't happen until you leave the field you are editing.
I hope this chapter has given you a fair idea of what is possible in Visual Basic Script as well as an idea of what the limitations are as well.
The programming structures presented in this chapter are nothing new to most intermediate programmers. They are a set of interlocking building blocks used in constructing programs. In later chapters you will see more complex and advanced application of these structures. VBScript continues to evolve even as I write this chapter and you may find some things altered. The release that I am working with added the Select...Case structure only the week before editing this chapter. The ByRef keyword was removed from the documentation at the same time. The best approach you can take is to experiment to see what works and what doesn't at the time you are working with VBScript. The ActiveX Control Pad makes an excellant tool for writing structured VBScript code and Chapter 3 takes you through its capabilities.
| Previous Chapter | Next Chapter |
| Search | Table of Contents | Book Home Page | Buy This Book |
| Que Home Page | Digital Bookshelf | Disclaimer |
To order books from QUE, call us at 800-716-0044 or 317-361-5400.
For comments or technical support for our books and software, select Talk to Us.
© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.